﻿using mqtt_app;
using System;

using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
using Newtonsoft.Json;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Xml.Linq;
using System.Threading;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ProgressBar;
using System.Security.Cryptography;
using System.Management;


namespace WindowsFormsApplication1
{
    

    public partial class Form1 : Form
    {
        MqttClient client;
        string gps_lat;
        string gps_lng;
        int post_mode;
        string[] wifi_str;
        int wifi_strnums=0;
        string[] lbs_str;
        Queue<byte[]> mqtt_msg_pub_queue = new Queue<byte[]>();
        

        //System.DateTime currentTime = new System.DateTime();
        //int RichTextBox1_lenth = 0;
        //字符串转16进制字节组：
        public static byte[] strToHexByte(string hexString)
        {
            hexString = hexString.Replace(" ", "");   //去除空格
            if ((hexString.Length % 2) != 0)     //判断hexstring的长度是否为偶数
            {
                hexString += "";
            }
            //声明一个长度为hexstring长度一半的字节组returnBytes
            byte[] returnBytes = new byte[hexString.Length / 2];

            for (int i = 0; i < returnBytes.Length; i++)
            {
                //将hexstring的两个字符转换成16进制的字节组
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            }
            return returnBytes;
        }



        //字节组转换成16进制的字符串：
        public static string byteToHexStr(byte[] bytes, UInt32 length)
        {
            string returnStr = "";
            if (bytes != null)
            {
                for (int i = 0; i < length; i++)
                {
                    returnStr += bytes[i].ToString("X2") + " ";      //byte转16进制字符
                }
            }
            return returnStr;
        }
        System.Timers.Timer tmr = new System.Timers.Timer();
        System.Timers.Timer send_cfg_tmr = new System.Timers.Timer();
        public Form1()
        {

            InitializeComponent();

            send_cfg_tmr.Elapsed+= new System.Timers.ElapsedEventHandler(OncfgTmrTrg);
            send_cfg_tmr.Interval = 1000;
            send_cfg_tmr.AutoReset = true;
            send_cfg_tmr.Enabled = false;

            tmr.Elapsed += new System.Timers.ElapsedEventHandler(OnTmrTrg);
            tmr.Interval = 1000;
            tmr.AutoReset = true; //true-一直循环 ，false-循环一次   
            // tmr.SynchronizingObject = this; //运行在主线程上
            tmr.Enabled = false;
            CheckForIllegalCrossThreadCalls = false;
        }
        // sub后的操作
         void client_MqttMsgSubscribed(object sender, MqttMsgSubscribedEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("Subscribed for id = " + e.MessageId);
           
           // textBox_output.Text += "[" + System.DateTime.Now.ToString("F")+"]"+ e.MessageId + "\r\n";
            
        }
        // 接受消息后的操作
         void client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
        {
            Int32 msg_len=e.Message.Length;
            
            System.Diagnostics.Debug.WriteLine("Received = " + Encoding.UTF8.GetString(e.Message) + " on topic " + e.Topic);
            //textBox_output.Text += "Received = " + Encoding.UTF8.GetString(e.Message) + " on topic " + e.Topic + "\r\n";
            
           // textBox_output.Text += "[" + System.DateTime.Now.ToString("F") + "] MQTT[TOPIC:" + e.Topic+"]接收"+ System.Text.Encoding.Default.GetBytes(Encoding.UTF8.GetString(e.Message)).Length + "字节\r\n"+Encoding.UTF8.GetString(e.Message) + "\r\n";
            OutMsg(richTextBox1, "[" + System.DateTime.Now.ToString("F") + "] MQTT[TOPIC:" + e.Topic + "]接收" + msg_len + "字节：",Color.Blue);
            
            //OutMsg(richTextBox1, Encoding.UTF8.GetString(e.Message) + "\r\n", Color.Red);


            
            if (e.Message[0] > 0x30 && e.Message[1]>0x30)//字符串
            {
                OutMsg(richTextBox1, Encoding.UTF8.GetString(e.Message) + "\r\n", Color.Red);
                recive_msg_explan(Encoding.UTF8.GetString(e.Message));
            }
            else
            {
                OutMsg(richTextBox1, byteToHexStr(e.Message, (uint)msg_len) + "\r\n", Color.Red);
                reive_msg_hex_explan(e.Message, (uint)msg_len);
                if(mqtt_msg_pub_queue.Count>0)
                {
                    string[] topic = { "" };
                    topic[0] = textBox_pub_topic.Text;
                    
                    ushort msgId = client.Publish(topic[0], // topic
                                                mqtt_msg_pub_queue.Dequeue(), // message body
                                               1, // pub的QoS level
                                                false); // retainid
                                                        //Console.WriteLine("pub msg : " + msg[0]);
                    OutMsg(richTextBox1, "发送历史消息：" + msgId,Color.Black);                                                                                 
                }
            }
            


        }
    // 发布消息后的操作
    void client_MqttMsgPublished(object sender, MqttMsgPublishedEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("MessageId = " + e.MessageId + " Published = " + e.IsPublished);
           // textBox_output.Text += "MessageId = " + e.MessageId + " Published = " + e.IsPublished + "\r\n";
        }
        // 关闭连接后的操作
         void client_ConnectionClosed(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("connect closed");
            //textBox_output.Text += "connect closed\r\n";
            Mqtt_client_state = false;
            button1.Text = "连接服务器";
            button1.ForeColor = Color.Green;
            OutMsg(richTextBox1, "与服务器的连接已断开", Color.Red);
        }
        // 取消sub后的操作
         void client_MqttMsgUnsubscribed(object sender, MqttMsgUnsubscribedEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("connect closed");
            
            //textBox_output.Text += "connect closed\r\n";
        }
         bool mqtt_client_connect_server()
        {
            string server_add ;
            int server_port;
            string user  ;
            string pwd  ;
            string clientid  ; // 获取一个独一无二的id
           

            server_add = comboBox_serveradd.Text  ;
            server_port = int.Parse(textBox_serverport.Text);
            user = textBox_user.Text;
            pwd = textBox_password.Text;
            clientid = textBox_client_id.Text;

             client = new MqttClient(server_add,
                                                server_port,
                                                false, // 开启TLS
                                                MqttSslProtocols.TLSv1_0, // TLS版本
                                                null,
                                                null
                                               );
            client.ProtocolVersion = MqttProtocolVersion.Version_3_1;
            System.Diagnostics.Debug.WriteLine(Guid.NewGuid().ToString());
            //textBox_output.Text += Guid.NewGuid().ToString();
           // textBox_output.Text +="\r\n";
            byte code = client.Connect(clientid,
                                        user,
                                        pwd,
                                        true, // cleanSession
                                        600); // keepAlivePeriod
            System.Diagnostics.Debug.WriteLine(code);
            //textBox_output.Text += code;
            //textBox_output.Text += "\r\n";
            System.Diagnostics.Debug.WriteLine(client.IsConnected);
            //textBox_output.Text += client.IsConnected;
           // textBox_output.Text += "\r\n";
            client.MqttMsgPublishReceived += client_MqttMsgPublishReceived;
            client.MqttMsgSubscribed += client_MqttMsgSubscribed;
            client.MqttMsgUnsubscribed += client_MqttMsgUnsubscribed;
            client.MqttMsgPublished += client_MqttMsgPublished;
            client.ConnectionClosed += client_ConnectionClosed;
            //client.Subscribe(topic, qosLevels); // sub 的qos=1

            // client.Disconnect();
            return client.IsConnected;
        }
        private void OutMsg(RichTextBox rtb, string msg, Color color)
        {
            rtb.Invoke(new EventHandler(delegate
            {
                rtb.SelectionStart = rtb.Text.Length;//设置插入符位置为文本框末
                rtb.SelectionColor = color;//设置文本颜色
                rtb.AppendText(msg + "\r\n");//输出文本，换行
                rtb.ScrollToCaret();//滚动条滚到到最新插入行
            }));
        }
        /// <param name="url"></param>
        /// <param name="method">默认GET，空则补充为GET</param>
        /// <param name="contenttype">默认json，空则补充为json</param>
        /// <param name="header">请求头部</param>
        /// <param name="data">请求body内容</param>
        /// <returns></returns>
        public static string Http(string url, string method = "GET", string contenttype = "application/json;charset=utf-8", Hashtable header = null, string data = null)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = string.IsNullOrEmpty(method) ? "GET" : method;
            request.ContentType = string.IsNullOrEmpty(contenttype) ? "application/json;charset=utf-8" : contenttype;
            if (header != null)
            {
                foreach (var i in header.Keys)
                {
                    request.Headers.Add(i.ToString(), header[i].ToString());
                }
            }
            if (!string.IsNullOrEmpty(data))
            {
                Stream RequestStream = request.GetRequestStream();
                byte[] bytes = Encoding.UTF8.GetBytes(data);
                RequestStream.Write(bytes, 0, bytes.Length);
                RequestStream.Close();
            }
            //if(request.GetResponse ()!=null)
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream ResponseStream = response.GetResponseStream();
            StreamReader StreamReader = new StreamReader(ResponseStream, Encoding.GetEncoding("utf-8"));
            string re = StreamReader.ReadToEnd();
            StreamReader.Close();
            ResponseStream.Close();
            return re;
        }
        string[] positing_mode = { "未知", "GNSS", "WIFI+LBS" };
        string[] lock_state = { "已佩戴", "未佩戴" };
        string[] band_state = { "正常", "拆卸" };
        string[] charg_state = { "未充电","充电中"};
        enum upload_proty_index
        {
            _INDEX_CMD=0,
            _INDEX_IMEI,
            _INDEX_LOC_TYPE,
            _INDEX_LOC_LAT,
            _INDEX_LOC_LONG,
            _INDEX_LOC_TAMP,
            _INDEX_STEP_COUNT,
            _INDEX_BATTERY,
            _INDEX_RSSI,
            _INDEX_WIFI_INFO,
            _INDEX_LBS_INFO,
            _INDEX_HEART_VAL,
            _INDEX_SPO2_VAL,
            _INDEX_WARNING_FLAG,
            _INDEX_NET_TYPE,
            _INDEX_LOCK_STATE,
            _INDEX_CHARGE_STATE,
            _INDEX_BAND_STATE,
            
            _INDEX_OPERATOR,
            _INDEX_UPLOAD_TAMP,
            _INDEX_IS_HISTORY
        }
        long last_rev_tamp=0;
        long time_diff = 0;
        void location_explan(string[] arr)
        {
            int item_nums = 0;
            foreach (string s in arr)
            {
                Console.WriteLine(s);
                item_nums++;
            }
            
            //
            for (upload_proty_index i = 0; i < (upload_proty_index)item_nums; i++)
            {
                switch (i)
                {
                    case upload_proty_index._INDEX_IMEI:
                        OutMsg(richTextBox1, "IMEI：" + arr[(int)i] + "\r\n", Color.Red);

                        break;
                    case upload_proty_index._INDEX_LOC_TYPE:
                        OutMsg(richTextBox1, "定位方式：" + positing_mode[Convert.ToInt32(arr[(int)i])+1], Color.YellowGreen);
                        int.TryParse(arr[(int)i], out post_mode);

                        break;
                    case upload_proty_index._INDEX_LOC_LAT:
                        OutMsg(richTextBox1, "GPS经度：" + arr[(int)i], Color.YellowGreen);
                        gps_lat = arr[(int)i];
                        break;
                    case upload_proty_index._INDEX_LOC_LONG:
                        OutMsg(richTextBox1, "GPS纬度：" + arr[(int)i], Color.YellowGreen);
                        gps_lng = arr[(int)i];
                        break;
                    case upload_proty_index._INDEX_LOC_TAMP:
                        //OutMsg(richTextBox1, "定位时间：" + arr[(int)i], Color.YellowGreen);
                        long tamps = Convert.ToInt32(arr[(int)i]);
                        time_diff = tamps - last_rev_tamp;
                        OutMsg(richTextBox1, "定位时间：" + DateTimeOffset.FromUnixTimeSeconds(tamps - 8 * 60 * 60).LocalDateTime, Color.YellowGreen);
                        last_rev_tamp= tamps;
                        break;
                    case upload_proty_index._INDEX_STEP_COUNT:
                        OutMsg(richTextBox1, "步数：" + arr[(int)i], Color.YellowGreen);

                        break;
                    case upload_proty_index._INDEX_BATTERY:
                        OutMsg(richTextBox1, "电池电量：" + arr[(int)i], Color.YellowGreen);

                        break;
                    case upload_proty_index._INDEX_RSSI:
                        OutMsg(richTextBox1, "rssi：" + arr[(int)i], Color.YellowGreen);

                        break;
                    case upload_proty_index._INDEX_WIFI_INFO:
                        // OutMsg (richTextBox1, "WIFI：" + arr[i] + "," + arr[i+1] + "," + arr[i+2], Color.YellowGreen);
                        OutMsg(richTextBox1, "WIFI：" + arr[(int)i], Color.YellowGreen);
                        wifi_str = arr[(int)i].Split('$');
                        wifi_strnums = 0;
                        foreach (string s in wifi_str)
                        {
                            wifi_str[wifi_strnums] = s.Replace("/", ",");

                            OutMsg(richTextBox1, wifi_str[wifi_strnums], Color.YellowGreen);
                            wifi_strnums++;
                        }
                        //for (int j = 0; j < wifi_strnums; j++)
                        //{
                        //    wifi_str[j] = wifi_str[j].Replace("/", ",");
                        //    //wifi_strnums++;

                        //}
                        break;
                    case upload_proty_index._INDEX_LBS_INFO:
                        OutMsg(richTextBox1, "基站：" + arr[(int)i], Color.YellowGreen);
                        lbs_str = arr[(int)i].Split('$');
                        wifi_strnums = 0;
                        foreach (string s in lbs_str)
                        {


                            lbs_str[wifi_strnums] = s.Replace("/", ",");

                            OutMsg(richTextBox1, lbs_str[wifi_strnums], Color.YellowGreen);
                            wifi_strnums++;
                        }
                        //for (int j = 0; j < wifi_strnums; j++)
                        //{
                        //    lbs_str[j] = lbs_str[j].Replace("/", ",");
                        //    //wifi_strnums++;
                        //    OutMsg(richTextBox1, lbs_str[j], Color.YellowGreen);
                        //}
                        break;
                    case upload_proty_index._INDEX_HEART_VAL:
                        OutMsg(richTextBox1, "心率：" + arr[(int)i], Color.YellowGreen);

                        break;
                    case upload_proty_index._INDEX_SPO2_VAL:
                        OutMsg(richTextBox1, "spo2：" + arr[(int)i], Color.YellowGreen);

                        break;
                    case upload_proty_index._INDEX_WARNING_FLAG:
                        OutMsg(richTextBox1, "报警：" + arr[(int)i], Color.YellowGreen);

                        break;
                    case upload_proty_index._INDEX_NET_TYPE:
                        OutMsg(richTextBox1, "网络类型：" + arr[(int)i], Color.YellowGreen);

                        break;
                    case upload_proty_index._INDEX_LOCK_STATE:
                        OutMsg(richTextBox1, "锁扣状态：" + lock_state[Convert.ToInt32(arr[(int)i])], Color.YellowGreen);

                        break;
                    case upload_proty_index._INDEX_CHARGE_STATE:
                        OutMsg(richTextBox1, "充电状态：" + charg_state[Convert.ToInt32(arr[(int)i])], Color.YellowGreen);

                        break;
                    case upload_proty_index._INDEX_BAND_STATE:
                        OutMsg(richTextBox1, "腕带状态：" + band_state[Convert.ToInt32(arr[(int)i])], Color.YellowGreen);

                        break;
                    case upload_proty_index._INDEX_OPERATOR:
                        OutMsg(richTextBox1, "网络运营商：" + arr[(int)i], Color.YellowGreen);

                        break;
                    case upload_proty_index._INDEX_UPLOAD_TAMP:
                            //OutMsg(richTextBox1, "上报时间：" + arr[(int)i], Color.YellowGreen);
                            OutMsg(richTextBox1, "上报时间：" + DateTimeOffset.FromUnixTimeSeconds(Convert.ToInt32(arr[(int)i])-8*60*60).LocalDateTime, Color.YellowGreen);
                        break;
                    case upload_proty_index._INDEX_IS_HISTORY:
                        OutMsg(richTextBox1, "是否是历史数据：" + arr[(int)i], Color.YellowGreen);

                        break;
                    //case 21:
                    //    OutMsg (richTextBox1, "上报时间：" + arr[i], Color.YellowGreen);

                    //    break;
                    //case 22:
                    //    OutMsg (richTextBox1, "是否是历史数据：" + arr[i], Color.YellowGreen);

                    //break;

                    default:

                        break;
                }
            }
            if(checkBox2.Checked== true)
                get_map_location(post_mode+1,arr[1], gps_lat, gps_lng, wifi_str, lbs_str, blemac);
        }
        string[] Dev_connect_type = { "上电复位", "PCA复位" ,"REST引脚复位", " 系统软件复位", " 看门狗复位", " 系统异常复位", " 断网重连" };
        enum DEV_PROP_I{
            PROP_CFG_ACTIVE = 0x01,//激活
            PROP_CFG_USERINFO,//用户信息
            PROP_CFG_AOA_INTERVAL,//AOA定位间隔
            PROP_CFG_DEV_TIME,//设备时间
            PROP_CFG_DOWN_LINK_REQUEST_INTERVAL,//请求下行数据间隔
            PR0P_CFG_SERVER_INFO,//服务器信息
            PROP_CFG_USER_PWD_INFO,//用户名密码
            PROP_CFG_OUTSIDE_LOC_MODE,//定位模式
            PROP_CFG_OUTSIDE_LOC_INTERVAL,//定位间隔
            PROP_CFG_OUTSIDE_LOC_TACTICS,//定位策略            
            PROP_CFG_NETHEAR_INTERVAL,//心跳间隔
            PROP_CFG_HUMAN_SIGNS_MEASURE_INTERVAL,//体征测量间隔
            PROP_CFG_HUMAN_SIGNS_MEASURE_TIME,//体征测量时间
            PROP_CFG_ELEC_FENCE_FLAG,//电子围栏
            PROP_CFG_HEART_TH,
            PROP_CFG_SPO2_TH,
            PROP_CFG_BAT_TH,
            PROP_CTRL_DEV = 0x20,//控制设备
            PROP_MSG_SENDER = 0x30,//消息发送者
            PROP_MSG_CONTEN,//消息内容
            PROP_MSG_UID,//消息ID
            PROP_MSG_TYPE,
            PROP_LTE_IMEI = 0x80,//模块IMEI
            PROP_LTE_ICCID,//模块ICCID
            PROP_DEV_SN,//设备序列号
            PROP_DEV_MAC,//设备MAC地址
            PROP_DEV_FW_VER,//设备固件版本
            PROP_DEV_HW_VER,//设备硬件版本
            PROP_DEV_MODEL,//设备型号
            PROP_DEV_BAT_SOC = 0x90,//电池电量
            PROP_DEV_BAT_VOLTAGE,   //电池电压
            PROP_DEV_BAT_CHARGE_STA,//电池充电状态
            PROP_DEV_LATCH_STA,//锁扣状态
            PROP_DEV_BANDE_STA,//腕带
            PROP_DEV_SOS_STA,//SOS
            PROP_DEV_WARNING_STA,
            PROP_SIGN_HEART = 0xa0,//心率
            PROP_SIGN_SPO2,//SpO2
            PROP_SIGN_BP,//血压
            PROP_SIGN_STEP,//步数
            PROP_MEMS_ACC = 0xb0,//加速度
            PROP_MEMS_GYRO,//陀螺仪
            PROP_LOC_TYPE = 0xc0,//定位类型
            PROP_LOC_COORD,//坐标
            PROP_LOC_TAMPS,//时间戳
            PROP_LOC_HDOP,//水平精度
            PROP_LOC_PDOP,//垂直精度
            PROP_LOC_GSPEED,//速度
            PROP_LOC_COURSE,//航向
            PROP_LTE_NET_TYPE,//网络类型
            PROP_LTE_OPERATOR,//运营商
            PORP_LTE_CSQ,//信号质量
            PROP_LTE_WIFI,
            PROP_LTE_LBS,//基站
            PROP_LOC_UPDATE_TAMPS,
            PROP_LOC_IS_HISTORY,//是否历史数据
            PORP_ACK = 0xd0,

        }
        
        void Intal_data_explan(string[] arr)
        {
            int item_nums = 0;
            foreach (string s in arr)
            {
                Console.WriteLine(s);
                item_nums++;
            }

            //
            for (int i = 0; i < item_nums; i++)
            {
                switch (i)
                {
                    case 1:
                        OutMsg(richTextBox1, "IMEI：" + arr[i] , Color.Red);

                        break;
                    case 2:
                        OutMsg(richTextBox1, "ICCID：" + arr[i], Color.YellowGreen);

                        break;
                    case 3:
                        OutMsg(richTextBox1, "MAC：" + arr[i], Color.Red);

                        break;                   
                    case 4:
                        OutMsg(richTextBox1, "SN：" + arr[i], Color.YellowGreen);

                        break;
                    case 5:
                        OutMsg(richTextBox1, "设备类型：" + arr[i] , Color.YellowGreen);

                        break;
                    case 6:
                        OutMsg(richTextBox1, "连接类型：" + Dev_connect_type[Convert.ToInt32(arr[i])], Color.YellowGreen);

                        break;
                    case 7:
                        OutMsg(richTextBox1, "硬件版本：" + arr[i] , Color.YellowGreen);

                        break;
                    case 8:
                        OutMsg(richTextBox1, "软件版本：" + arr[i] , Color.YellowGreen);

                        break;
                    default:
                        break;
                }
            }
        }
        string[] net_type_str = { "GPRS", "LTE" };
        string[] net_oper_str = { "中国移动","中国联通","中国电信"};
        string[] active_str = { "未激活","已激活"};
        string[] locmode_str = { "GNSS优先", "LBS优先" };
        string[] loctatic_str = { "位置优先", "时间优先" };
        string[] room_in_out_str = { "室内", "室外" };
        string[] ctrl_cmd = { "读取设备配置", "获取设备信息", "获取设备数据" };
        byte[] blemac;
        private unsafe void reive_msg_hex_explan(byte[]buf ,uint len)
        {
            UInt16 index = 0;
            UInt16 crc_ckeck;
            int data_len = buf[1] * 256 + buf[0];
            int crc = (UInt16)buf[len -1] <<8| buf[len-2];
            fixed (byte* ptr = &buf[2])
            {
                crc_ckeck = CRC16(ptr, (ushort)(data_len)); 
            }
            if(crc!=crc_ckeck)
            {
                OutMsg(richTextBox1, "CRC错误"+crc_ckeck, Color.Red);
                return;
            }
            byte[] imei=new byte[16];
            byte[] coord=new byte[64];
            byte[] tamps = new byte[4];
            index = 2;
            string imei_str="";
            uint need_loc = 0;
            while (index < len - 2)
            {
                byte prop_lenth = buf[index];
                byte prop_type = buf[index + 1];
                Debug.WriteLine("prop_type:" + prop_type.ToString("X2"));
                Debug.WriteLine("prop_len:" + (prop_lenth).ToString("X2")+"\r\n");
                switch ((DEV_PROP_I)prop_type)
                {
                    case DEV_PROP_I.PROP_CFG_ACTIVE:
                        OutMsg(richTextBox1, "激活:" + active_str[buf[index + 2]], Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_CFG_USERINFO:
                        byte[] user_info = new byte[64];
                        Array.Copy(buf, index + 2, user_info, 0, prop_lenth);
                        OutMsg(richTextBox1, "用户信息:" + Encoding.UTF8.GetString(user_info), Color.YellowGreen);
                        OutMsg(richTextBox1, "", Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_CFG_AOA_INTERVAL:
                        OutMsg(richTextBox1, "AOA定位间隔:" + buf[index + 2]+"ms", Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_CFG_DEV_TIME:
                        Array.Copy(buf, index + 2, tamps, 0, prop_lenth);
                        long loctamps = tamps[3] << 24 | tamps[2] << 16 | tamps[1] << 8 | tamps[0];
                        OutMsg(richTextBox1, "设备时间：" + DateTimeOffset.FromUnixTimeSeconds(loctamps - 8 * 60 * 60).LocalDateTime, Color.YellowGreen);

                        break;

                    case DEV_PROP_I.PROP_CFG_DOWN_LINK_REQUEST_INTERVAL:
                        OutMsg(richTextBox1, "AOA请求下行数据间隔:" + buf[index + 2] + "s", Color.YellowGreen);
                        break;

                    case DEV_PROP_I.PR0P_CFG_SERVER_INFO:
                        byte[] mqtt_server_info = new byte[64];
                        Array.Copy(buf, index + 2, mqtt_server_info, 0, prop_lenth);
                        OutMsg(richTextBox1, "MQTT server:" + Encoding.UTF8.GetString(mqtt_server_info) + " \r\n", Color.YellowGreen);
                        OutMsg(richTextBox1, "", Color.YellowGreen);
                        break;

                    case DEV_PROP_I.PROP_CFG_USER_PWD_INFO:
                        byte[] mqtt_user_info = new byte[64];
                        Array.Copy(buf, index + 2, mqtt_user_info, 0, prop_lenth);
                        OutMsg(richTextBox1, "MQTT user:" + Encoding.UTF8.GetString(mqtt_user_info) , Color.YellowGreen);
                        OutMsg(richTextBox1, "", Color.YellowGreen);
                        break;

                    case DEV_PROP_I.PROP_CFG_OUTSIDE_LOC_MODE:
                        OutMsg(richTextBox1, "室外定位模式:" + locmode_str[buf[index + 2]], Color.YellowGreen);
                        break;

                    case DEV_PROP_I.PROP_CFG_OUTSIDE_LOC_TACTICS:
                        OutMsg(richTextBox1, "室外定位策略:" + loctatic_str[buf[index + 2]], Color.YellowGreen);
                        break;

                    case DEV_PROP_I.PROP_CFG_OUTSIDE_LOC_INTERVAL:
                        byte[] loc_int_buf = new byte[2];
                        UInt16 loc_interval;
                        Array.Copy(buf, index + 2, loc_int_buf, 0, prop_lenth);
                        loc_interval = (UInt16)(loc_int_buf[1] << 8 | loc_int_buf[0]);
                        OutMsg(richTextBox1, "室外定位间隔:" + loc_interval+"S", Color.YellowGreen);
                        break;

                    case DEV_PROP_I.PROP_CFG_NETHEAR_INTERVAL:
                        byte[] net_heart_buf = new byte[2];
                        UInt16 net_heart;
                        Array.Copy(buf, index + 2, net_heart_buf, 0, prop_lenth);
                        net_heart = (UInt16)(net_heart_buf[1] << 8 | net_heart_buf[0]);
                        OutMsg(richTextBox1, "4G心跳间隔:" + net_heart+"S", Color.YellowGreen);
                        break;

                    case DEV_PROP_I.PROP_CFG_HUMAN_SIGNS_MEASURE_INTERVAL:
                        byte[] measure_int_buf = new byte[2];
                        UInt16 measure_int;
                        Array.Copy(buf, index + 2, measure_int_buf, 0, prop_lenth);
                        measure_int = (UInt16)(measure_int_buf[1] << 8 | measure_int_buf[0]);
                        OutMsg(richTextBox1, "测量间隔:" + measure_int + "S", Color.YellowGreen);
                        break;

                    case DEV_PROP_I.PROP_CFG_HUMAN_SIGNS_MEASURE_TIME:
                        byte[] measure_time_buf = new byte[2];
                        UInt16 measure_time;
                        Array.Copy(buf, index + 2, measure_time_buf, 0, prop_lenth);
                        measure_time = (UInt16)(measure_time_buf[1] << 8 | measure_time_buf[0]);
                        OutMsg(richTextBox1, "测量时间:" + measure_time + "S", Color.YellowGreen);
                        break;

                    case DEV_PROP_I.PROP_CFG_ELEC_FENCE_FLAG:
                        OutMsg(richTextBox1, "室内室外标志:" +room_in_out_str[ buf[index + 2]], Color.YellowGreen);
                        break;

                    case DEV_PROP_I.PROP_CFG_HEART_TH:
                        OutMsg(richTextBox1, "心率报警阈值:" + buf[index + 2] + "," + buf[index+3], Color.YellowGreen);
                        break;

                    case DEV_PROP_I.PROP_CFG_SPO2_TH:
                        OutMsg(richTextBox1, "血氧报警阈值:" + buf[index + 2], Color.YellowGreen);
                        break;

                    case DEV_PROP_I.PROP_CFG_BAT_TH:
                        OutMsg(richTextBox1, "低电量报警阈值:" + buf[index + 2], Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_CTRL_DEV:
                        OutMsg(richTextBox1, "设备控制命令:" + buf[index + 2]+"--"+ ctrl_cmd[buf[index + 2]-1], Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_MSG_SENDER:
                        byte[] sender = new byte[64];
                        Array.Copy(buf, index + 2, sender, 0, prop_lenth);
                        OutMsg(richTextBox1, "消息标题:" + Encoding.UTF8.GetString(sender), Color.YellowGreen);
                        OutMsg(richTextBox1, "", Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_MSG_CONTEN:
                        byte[] content = new byte[64];
                        Array.Copy(buf, index + 2, content, 0, prop_lenth);
                        OutMsg(richTextBox1, "消息内容:" + Encoding.UTF8.GetString(content), Color.YellowGreen);
                        OutMsg(richTextBox1, "", Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_MSG_TYPE: 
                        break;
                    case DEV_PROP_I.PROP_MSG_UID:
                        Array.Copy(buf, index + 2, tamps, 0, prop_lenth);
                        loctamps = tamps[3] << 24 | tamps[2] << 16 | tamps[1] << 8 | tamps[0];
                        OutMsg(richTextBox1, "msg uid：" + loctamps, Color.YellowGreen);
                       
                        break;

                    case DEV_PROP_I.PROP_LTE_IMEI:
                        {
                            
                            Array.Copy(buf, index + 2, imei, 0, prop_lenth);
                            imei_str = Encoding.UTF8.GetString(imei);
                            OutMsg(richTextBox1, "IMEI:"+Encoding.UTF8.GetString(imei) , Color.Red);
                            OutMsg(richTextBox1, "\r\n", Color.Red);
                        }
                        break;
                    case DEV_PROP_I.PROP_LTE_ICCID:
                        byte[]iccid = new byte[32];
                        Array.Copy(buf, index + 2, iccid, 0, prop_lenth);
                        OutMsg(richTextBox1, "ICCID:" + Encoding.UTF8.GetString(iccid), Color.Red);
                        OutMsg(richTextBox1, "\r\n", Color.Red);
                        break;
                    case DEV_PROP_I.PROP_DEV_SN:
                        byte[] sn = new byte[32];
                        Array.Copy(buf, index + 2, sn, 0, prop_lenth);
                        OutMsg(richTextBox1, "SN:" + Encoding.UTF8.GetString(sn), Color.Red);
                        OutMsg(richTextBox1, "\n", Color.Red);
                        break;
                    case DEV_PROP_I.PROP_DEV_MAC:
                        blemac = new byte[6];
                        Array.Copy(buf, index + 2, blemac, 0, prop_lenth);
                        string macsting = byteToHexStr(blemac, (uint)blemac.Length);
                        if (checkBox1.Checked == true)
                            if (textBox1.Text != "")
                            {
                                Debug.WriteLine(macsting);
                                if (macsting != textBox1.Text)
                                {
                                    OutMsg(richTextBox1, "mac 地址不匹配，解析结束", Color.Red);
                                    return;
                                }

                                    
                            }

                        OutMsg(richTextBox1, "MAC:"+ blemac[0].ToString("X2") + " " + blemac[1].ToString("X2") + " " + blemac[2].ToString("X2") + " " + blemac[3].ToString("X2") + " " + blemac[4].ToString("X2") + " " + blemac[5].ToString("X2"), Color.Red);
                        
                        break;
                    case DEV_PROP_I.PROP_DEV_HW_VER:
                        byte[] h_ver = new byte[3];
                        Array.Copy(buf, index + 2, h_ver, 0, prop_lenth);
                        OutMsg(richTextBox1, "硬件版本:" + h_ver[0].ToString()+"." + h_ver[1].ToString() + "." + h_ver[2].ToString(), Color.Red);
                        OutMsg(richTextBox1, "\n", Color.Red);
                        break;
                    case DEV_PROP_I.PROP_DEV_FW_VER:
                        byte[] f_ver = new byte[3];
                        Array.Copy(buf, index + 2, f_ver, 0, prop_lenth);
                        OutMsg(richTextBox1, "软件版本:" + f_ver[0].ToString() + "." + f_ver[1].ToString() + "." + f_ver[2].ToString(), Color.Red);
                        OutMsg(richTextBox1, "\n", Color.Red);
                        break;
                    case DEV_PROP_I.PROP_DEV_MODEL:

                        byte[] model = new byte[20];
                        Array.Copy(buf, index + 2, model, 0, prop_lenth);
                        OutMsg(richTextBox1, "型号:" + Encoding.UTF8.GetString(model), Color.Red);
                        OutMsg(richTextBox1, "\n", Color.Red);
                        break;
                    case DEV_PROP_I.PROP_DEV_BAT_SOC:
                        OutMsg(richTextBox1, "电量:" + buf[index+2], Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_DEV_BAT_VOLTAGE:
                        byte [] voltage = new byte[2];
                        UInt16 v;
                        Array.Copy(buf, index + 2, voltage, 0, prop_lenth);
                        v = (UInt16)(voltage[1] << 8 | voltage[0]);
                        OutMsg(richTextBox1, "电压:" + v.ToString()+"mV", Color.YellowGreen);
                        
                        break;
                    case DEV_PROP_I.PROP_DEV_BAT_CHARGE_STA:
                        OutMsg(richTextBox1, "充电状态:" + buf[index + 2], Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_DEV_LATCH_STA:
                        OutMsg(richTextBox1, "锁扣状态:" + buf[index + 2], Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_DEV_BANDE_STA:
                        OutMsg(richTextBox1, "腕带状态:" + buf[index + 2], Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_DEV_SOS_STA:
                        OutMsg(richTextBox1, "SOS状态:" + buf[index + 2], Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_DEV_WARNING_STA:
                        byte warning_sta = buf[index + 2];
                        OutMsg(richTextBox1,"报警状态："+ warning_sta, Color.YellowGreen);
                        //bit0：低电量报警
                        //bit1：腕带报警
                        //bit2：锁扣
                        //bit3：sos报警
                        //bit4：心率报警
                        //bit5：血氧报警
                        //bit6: 保留
                        //bit7: 保留
                        OutMsg(richTextBox1, "低电量报警：" + ((warning_sta&0x01)>0?1:0), Color.YellowGreen);
                        OutMsg(richTextBox1, "腕带报警：" + (warning_sta & 0x01<<1), Color.YellowGreen);
                        OutMsg(richTextBox1, "锁扣：" + (warning_sta & 0x01<<2), Color.YellowGreen);
                        OutMsg(richTextBox1, "sos报警：" + ((warning_sta & 0x01<<3) > 0 ? 1 : 0), Color.YellowGreen);
                        OutMsg(richTextBox1, "心率报警：" + (warning_sta & 0x01<<4), Color.YellowGreen);
                        OutMsg(richTextBox1, "血氧报警：" + (warning_sta & 0x01<<5), Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_SIGN_HEART:
                        byte[] heart_buf = new byte[2];
                        Int16 heart;
                        Array.Copy(buf, index + 2, heart_buf, 0, prop_lenth);
                        heart = (Int16)(heart_buf[1] << 8 | heart_buf[0]);
                        OutMsg(richTextBox1, "心率:" + heart.ToString(), Color.YellowGreen);
                        break;

                    case DEV_PROP_I.PROP_SIGN_SPO2:
                        byte[] spo2_buf = new byte[2];
                        Int16 spo2;
                        Array.Copy(buf, index + 2, spo2_buf, 0, prop_lenth);
                        spo2 = (Int16)(spo2_buf[1] << 8 | spo2_buf[0]);
                        OutMsg(richTextBox1, "血氧:" + spo2.ToString(), Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_SIGN_STEP:
                        byte[] step_buf = new byte[2];
                        UInt16 step;
                        Array.Copy(buf, index + 2, step_buf, 0, prop_lenth);
                        step = (UInt16)(step_buf[1] << 8 | step_buf[0]);
                        OutMsg(richTextBox1, "计步:" + step.ToString(), Color.YellowGreen);
                        break;

                    case DEV_PROP_I.PROP_SIGN_BP:
                        OutMsg(richTextBox1, "血压:", Color.YellowGreen);
                        break;

                    case DEV_PROP_I.PROP_LOC_TYPE:
                        post_mode = buf[index + 2] ;
                        OutMsg(richTextBox1, "定位方式:" + positing_mode[buf[index+2]+1] , Color.YellowGreen);
                        need_loc = 1;
                        break;
                    case DEV_PROP_I.PROP_MEMS_ACC:
                        byte[] acc_buf = new byte[6];
                        Int16 x,y,z;
                        Array.Copy(buf, index + 2, acc_buf, 0, prop_lenth);
                        x = (Int16)(acc_buf[1] << 8 | acc_buf[0]);
                        y = (Int16)(acc_buf[3] << 8 | acc_buf[2]);
                        z = (Int16)(acc_buf[5] << 8 | acc_buf[4]);
                        OutMsg(richTextBox1, "ACC: " + x +","+y+","+z, Color.YellowGreen);
                        OutMsg(richTextBox1, "ACC: " + x * 0.061 + "mg," + y * 0.061 + "mg," + z * 0.061 + "mg", Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_MEMS_GYRO:
                        byte[] gyro_buf = new byte[6];
                        Int16 gx, gy, gz;
                        Array.Copy(buf, index + 2, gyro_buf, 0, prop_lenth);
                        gx = (Int16)(gyro_buf[1] << 8 | gyro_buf[0]);
                        gy = (Int16)(gyro_buf[3] << 8 | gyro_buf[2]);
                        gz = (Int16)(gyro_buf[5] << 8 | gyro_buf[4]);
                        OutMsg(richTextBox1, "GYRO: " + gx + "," + gy + "," + gz, Color.YellowGreen);
                        OutMsg(richTextBox1, "GYRO: " + gx*70 + "dps," + gy * 70 + "dps," + gz * 70+"dps", Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_LOC_COORD:
                        
                        Array.Copy(buf, index + 2, coord, 0, prop_lenth);
                        Array.Resize<byte>(ref coord, (int)prop_lenth);
                        OutMsg(richTextBox1, "坐标:" + Encoding.UTF8.GetString(coord) , Color.YellowGreen);
                        
                        string[] arr = Encoding.UTF8.GetString(coord).Split(',');
                        gps_lat = arr[0];
                        gps_lng= arr[1];
                        break;
                    case DEV_PROP_I.PROP_LOC_TAMPS:
                        Array.Copy(buf, index + 2, tamps, 0, prop_lenth);
                        loctamps = tamps[3] << 24 | tamps[2] << 16 | tamps[1] << 8 | tamps[0];
                        OutMsg(richTextBox1, "定位时间：" + DateTimeOffset.FromUnixTimeSeconds(loctamps - 8 * 60 * 60).LocalDateTime, Color.YellowGreen);

                        break;
                    case DEV_PROP_I.PROP_LOC_HDOP:
                        byte[] hdop_buf = new byte[4];
                        Array.Copy(buf, index + 2, hdop_buf, 0, prop_lenth);
                        double fhdop= BitConverter.ToSingle(hdop_buf,0);
                        OutMsg(richTextBox1, "HDOP:" + fhdop.ToString(), Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_LOC_PDOP:
                        byte[] pdop_buf = new byte[4];
                        Array.Copy(buf, index + 2, pdop_buf, 0, prop_lenth);
                        double fpdop = BitConverter.ToSingle(pdop_buf, 0);
                        OutMsg(richTextBox1, "PDOP:" + fpdop.ToString(), Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_LOC_GSPEED:
                        byte[] gspeed_buf = new byte[4];
                        Array.Copy(buf, index + 2, gspeed_buf, 0, prop_lenth);
                        double fgspeed = BitConverter.ToSingle(gspeed_buf, 0);
                        OutMsg(richTextBox1, "地面速度:" + fgspeed.ToString(), Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_LOC_COURSE:
                        byte[] course_buf = new byte[4];
                        Array.Copy(buf, index + 2, course_buf, 0, prop_lenth);
                        double fcourse = BitConverter.ToSingle(course_buf, 0);
                        OutMsg(richTextBox1, "地面航向:" + fcourse.ToString(), Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_LTE_NET_TYPE:
                        OutMsg(richTextBox1, "网络类型:" + net_type_str[buf[index + 2]], Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_LTE_OPERATOR:
                        OutMsg(richTextBox1, "运营商:" + net_oper_str[buf[index + 2]] , Color.YellowGreen); 
                        break;
                    case DEV_PROP_I.PORP_LTE_CSQ: 
                        OutMsg(richTextBox1, "信号质量:" + buf[index + 2] , Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_LTE_WIFI:
                        OutMsg(richTextBox1, "WIFI:" , Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_LTE_LBS:
                        OutMsg(richTextBox1, "LBS:" , Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_LOC_UPDATE_TAMPS:
                        Array.Copy(buf, index + 2, tamps, 0, prop_lenth);
                        long luptamps = tamps[3] << 24 | tamps[2] << 16 | tamps[1] << 8 | tamps[0];
                        
                        OutMsg(richTextBox1, "上传：" + DateTimeOffset.FromUnixTimeSeconds(luptamps - 8 * 60 * 60).LocalDateTime, Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PROP_LOC_IS_HISTORY:
                        OutMsg(richTextBox1, "历史数据:" + buf[index + 2] , Color.YellowGreen);
                        break;
                    case DEV_PROP_I.PORP_ACK:
                        int msg_uid;
                        Array.Copy(buf, index + 2, tamps, 0, prop_lenth);
                        msg_uid = tamps[3] << 24 | tamps[2] << 16 | tamps[1] << 8 | tamps[0];
                        OutMsg(richTextBox1, "ACK MSG ID：" + msg_uid.ToString(), Color.YellowGreen);
                        rev_msg_id = (UInt32)msg_uid;
                        if (send_msg_id == rev_msg_id)
                        {
                            OutMsg(richTextBox1, "发送成功", Color.Red);
                        }
                        else
                        {
                            OutMsg(richTextBox1, "发送ID:" + send_msg_id.ToString() + ",接收ID：" + rev_msg_id.ToString(), Color.Red);
                        }
                        break;
                    default:
                        break;
                }

                index = (UInt16)(index +prop_lenth + 2);
            }
            if (need_loc==1)
            {
                if (checkBox2.Checked == true)
                    get_map_location(post_mode + 1, imei_str, gps_lat, gps_lng, wifi_str, lbs_str, blemac);
                need_loc = 0;
            }
        }
        private void recive_msg_explan(string msg_str)
        {
            //string msg_str = Encoding.UTF8.GetString(e.Message);
            string[] arr = msg_str.Split(',');
            
            
            if (arr[0] == "16")
            {

                location_explan(arr);
                
            }
            else if(arr[0] == "18")
            {
                Intal_data_explan(arr);
            }

        }
    private void gs84_coord_show_map(string lat,string lng)
    {
            string[] arry;
            //string[] lng_s = lng.Split('/');
            //string[] lat_s = lat.Split('/');
            //double dlat = Convert.ToDouble(lng_s[0]) / 100;
            //double dlng = Convert.ToDouble(lat_s[0]) / 100;
            //Debug.WriteLine("lat:" + dlat.ToString() + " lng:" + dlng.ToString());
            //string lat_str = dlat.ToString();
            //int index = 0;
            //index = lat_str.IndexOf(".");
            //string di = lat_str.Substring(0, index);
            //string df = lat_str.Substring(index + 1);
            //lat_str = di + "." + Convert.ToString(Convert.ToInt32(df) / 60);
            //Debug.WriteLine("lat_di:" + di + " lat_df:" + df);
            //string lng_str = dlng.ToString();
            //index = lng_str.IndexOf(".");
            //di = lng_str.Substring(0, index);
            //df = lng_str.Substring(index + 1);
            //lng_str = di + "." + Convert.ToString(Convert.ToInt32(df) / 60);
            //string location_url = "https://restapi.amap.com/v3/assistant/coordinate/convert?locations=" + lat_str + "," + lng_str + "&coordsys=gps&output=csv&key=1420accbc6c11f1da4aeb8fb6fc75420";
            Debug.WriteLine("经度：{0}，纬度:{1}, {2},{3}",lat,lng,lat.Length,lng.Length);
            string location_url = "https://restapi.amap.com/v3/assistant/coordinate/convert?locations=" + lat + "," + lng + "&coordsys=gps&output=csv&key=1420accbc6c11f1da4aeb8fb6fc75420";
            System.Diagnostics.Debug.WriteLine(location_url);
            string request_str = Http(location_url);
            System.Diagnostics.Debug.WriteLine(request_str);
            OutMsg(richTextBox1, request_str, Color.Red);
            arry = request_str.Split(',');
            Root rt = JsonConvert.DeserializeObject<Root>(request_str);
            Debug.WriteLine(rt.status);
            Debug.WriteLine(rt.info);
            Debug.WriteLine(rt.infocode);
            Debug.WriteLine(rt.locations);
            string map_url = "http://m.amap.com/navi/?dest=" + rt.locations + "&destName="+ time_diff.ToString()+ "&hideRouteIcon=1&key=1420accbc6c11f1da4aeb8fb6fc75420";
            Debug.WriteLine(map_url);
            webBrowser1.Navigate(map_url, null, null, null);
        }
    private void get_map_location(int mode,string imei, string lat,string lng,string []wifi,string [] lbs, byte[]mac)
    {
            string wifi_string=null ;
            string lbs_string = null;
            int items = 0;
            int count = 0;
            string[] arry;
            mode = 1;
            //wifi_string = wifi[0]+";"+ wifi[1] + ";"+wifi[2] ;
            //lbs_string = lbs[0] + ";" + lbs[1] + ";" + lbs[2];
            string macsting = byteToHexStr(mac, (uint)mac.Length);
            if (checkBox1.Checked == true)
                if (textBox1.Text != "")
                {
                    Debug.WriteLine(macsting);
                    if(macsting != textBox1.Text)

                        return;
                }
            if (mode == 2)
            {
                
                items = wifi_str.Length;
                Debug.WriteLine("wifi_str items: " + items.ToString());
                foreach (string s in wifi_str)
                {
                    count++;
                    if (count < items)
                        wifi_string += (s + ";");
                    else
                        wifi_string += s;
                }
                items = lbs.Length;
                Debug.WriteLine("lbs_str items: " + items.ToString());
                count = 0;
                foreach (string s in lbs)
                {
                    count++;
                    if (count < items)
                        lbs_string += (s + ";");
                    else
                        lbs_string += s;
                }
                /*http://www.cellocation.com/api/*/
                string location_url = "http://api.cellocation.com:81/loc/?cl=" + lbs_string+ "&wl=" + wifi_string + "&coord=gcj02&output=csv";
                System.Diagnostics.Debug.WriteLine(location_url);
                string request_str = Http(location_url);
                System.Diagnostics.Debug.WriteLine(request_str);
                OutMsg(richTextBox1, request_str, Color.Red);
                arry = request_str.Split(',');
                if (arry[0] == "0")
                {
                    arry[4] = arry[4].Replace("\"", " ");
                    string map_url = "http://m.amap.com/navi/?dest=" + arry[2] + "," + arry[1] + "&destName="+ time_diff.ToString()+ "&hideRouteIcon=1&key=1420accbc6c11f1da4aeb8fb6fc75420";
                    Debug.WriteLine(map_url);
                    webBrowser1.Navigate(map_url, null, null, null);
                }
            }
            else if(mode==1)
            {
#if false
                string[] lng_s = lng.Split('/');
                string[] lat_s = lat.Split('/');
                double dlat = Convert.ToDouble(lng_s[0]) / 100;
                double dlng = Convert.ToDouble(lat_s[0]) / 100;
                Debug.WriteLine("lat:"+dlat.ToString()+" lng:"+dlng.ToString());
                string lat_str = dlat.ToString();
                int index = 0;
                index = lat_str.IndexOf(".");
                string di = lat_str.Substring(0, index);
                string df = lat_str.Substring(index + 1);
                lat_str = di + "." + Convert.ToString(Convert.ToInt32(df) / 60);
                Debug.WriteLine("lat_di:"+di+" lat_df:"+df);
                string lng_str = dlng.ToString();
                 index = lng_str.IndexOf(".");
                 di = lng_str.Substring(0, index);
                 df = lng_str.Substring(index + 1);
                lng_str = di + "." + Convert.ToString(Convert.ToInt32(df) / 60);
                string location_url = "https://restapi.amap.com/v3/assistant/coordinate/convert?locations="+ lat_str + "," + lng_str + "&coordsys=gps&output=csv&key=1420accbc6c11f1da4aeb8fb6fc75420";
                System.Diagnostics.Debug.WriteLine(location_url);
                string request_str = Http(location_url);
                System.Diagnostics.Debug.WriteLine(request_str);
                OutMsg(richTextBox1, request_str, Color.Red);
                arry = request_str.Split(',');
                Root rt = JsonConvert.DeserializeObject<Root>(request_str);
                Debug.WriteLine(rt.status);
                Debug.WriteLine(rt.info);                
                Debug.WriteLine(rt.infocode);
                Debug.WriteLine(rt.locations);
                string map_url = "http://m.amap.com/navi/?dest=" + rt.locations + "&destName=当前位置&hideRouteIcon=1&key=1420accbc6c11f1da4aeb8fb6fc75420";
                Debug.WriteLine(map_url);
                webBrowser1.Navigate(map_url, null, null, null);
#else
                gs84_coord_show_map(lat,lng);
#endif
            }
            
            
            

        }
        bool Mqtt_client_state = false;
        private void button1_Click(object sender, EventArgs e)
        {
            
            if (Mqtt_client_state == false)
            {
                if (comboBox_serveradd.Text != "")
                {
                    if (textBox_serverport.Text != "")
                    {
                        if (textBox_client_id.Text != "")
                        {
                            if (textBox_user.Text != "")
                            {
                                if (textBox_password.Text != "")
                                {
                                    if (mqtt_client_connect_server())
                                    {
                                        Mqtt_client_state = true;
                                        button1.Text = "断开连接";
                                        button1.ForeColor = Color.Red;
                                        OutMsg(richTextBox1, "连接服务器成功", Color.Green);
                                    }
                                }
                                else
                                    MessageBox.Show("密码不能为空");
                            }
                            else
                            {
                                MessageBox.Show("用户名不能为空");
                            }
                        }
                        else
                            MessageBox.Show("客户端ID不能为空");

                    }
                    else
                        MessageBox.Show("服务器端口不能为空");

                }
                else
                    MessageBox.Show("服务器地址不能为空");


            }
            else
            {
                client.Disconnect();
                Mqtt_client_state = false;
                button1.Text = "连接服务器";
                button1.ForeColor = Color.Green;
                OutMsg(richTextBox1, "与服务器的连接已断开",Color.Red);
            }
        }

    

        private void textBox3_TextChanged(object sender, EventArgs e)
        {

        }

        private void textBox4_TextChanged(object sender, EventArgs e)
        {

        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void textBox6_TextChanged(object sender, EventArgs e)
        {

        }

        private void button_sub_Click(object sender, EventArgs e)
        {
            if (Mqtt_client_state == true )
            {
                string[] topic = { "" };
                topic[0] = comboBox_subtopic.Text;

                byte[] qosLevels = new byte[] { MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE }; // qos=1
                client.Subscribe(topic, qosLevels);
                OutMsg(richTextBox1, "已订阅 topic: [" + topic[0] + "]\r\n", Color.Green);

            }
        }
        private void button_pub_Click(object sender, EventArgs e)
        {
            string[] topic = { "" };
            topic [0]= textBox_pub_topic.Text;
            string str = comboBox_pub.Text;
            byte [] msg = Encoding.UTF8.GetBytes( str);
            //byte[] msg = Encoding.UTF8.GetString(str);
            if (textBox_pub_topic.Text != "")
            {
                ushort msgId = client.Publish(topic[0], // topic
                                              msg, // message body
                                              0, // pub的QoS level
                                              false); // retainid
                                                      //Console.WriteLine("pub msg : " + msg[0]);
            }
        }
        /// <summary>
        /// 显示MAC地址
        /// </summary>
        /// <returns></returns>
        private string GetMAC()
        {
            string mac = "0";
            using (ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration"))
            {
                ManagementObjectCollection moc = mc.GetInstances();
                foreach (ManagementObject mo in moc)
                {
                    if ((bool)mo["IPEnabled"])
                    {
                        string[] tmpMac = mo["MacAddress"].ToString().Split(':');
                        for (int i = 0; i < tmpMac.Length; i++)
                        {
                            mac += tmpMac[i];
                        }
                    }
                }
            }
            return mac + "\r\n";
        }
        /// <summary>
        /// 获取本机CPU序列号
        /// </summary>
        /// <returns></returns>
        private string GetCPUID()
        {
            string CPUID = "0";
            using (ManagementClass mc = new ManagementClass("Win32_Processor"))
            {
                ManagementObjectCollection moc = mc.GetInstances();
                foreach (ManagementObject item in moc)
                {
                    CPUID += item["ProcessorId"].ToString().Trim();
                }
            }
            return CPUID + "\r\n";
        }

        /// <summary>
        /// 获取本机硬盘序列号   
        /// </summary>
        /// <returns></returns>
        private string GetHardID()
        {
            string HardID = "0";
            using (ManagementClass mc = new ManagementClass("Win32_DiskDrive"))
            {
                ManagementObjectCollection moc = mc.GetInstances();
                foreach (ManagementObject item in moc)
                {
                    HardID += item["Model"].ToString().Trim();
                }
            }
            return HardID + "\r\n";
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.comboBox_serveradd.SelectedIndex = 0;
            this.textBox_serverport.Text = "1883";
            this.comboBox_subtopic.SelectedIndex = 0;
            textBox_client_id.Text = GetMAC();

            // webBrowser1.Url = Encoding.GetEncoding( "http://m.amap.com/navi/?dest=116.470098,39.992838&destName=当前位置\r\n&hideRouteIcon=1&key=1420accbc6c11f1da4aeb8fb6fc75420");
            // webBrowser1.Navigate("http://m.amap.com/navi/?dest=103.971496,30.629776&destName=位置&hideRouteIcon=1&key=1420accbc6c11f1da4aeb8fb6fc75420", null, null, null);
            webBrowser1.Navigate("http://m.amap.com/navi/?dest=104.068244,30.6167103&destName=位置&hideRouteIcon=1&key=1420accbc6c11f1da4aeb8fb6fc75420", null, null, null);
            //webBrowser2.Navigate("http://api.cellocation.com:81/loc/?cl=460,0,32771,29080,-68;460,0,32771,42941,-95&wl=88:25:93:ef:dd:a4,-78;0a:25:93:ef:dd:a4,-78&coord=gcj02&output=csv");
            //OutMsg(richTextBox1, Http("http://api.cellocation.com:81/loc/?cl=460,0,32771,29080,-68;460,0,32771,42941,-95&wl=88:25:93:ef:dd:a4,-78;0a:25:93:ef:dd:a4,-78&coord=gcj02&output=csv"), Color.Red);
        }

        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {

        }

        private void 升级ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form2 f2 = new Form2();
            //f2.MdiParent = this;
            f2.Show();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //传入我们的实体类还有需要解析的JSON字符串这样就OK了。然后就可以通过实体类使用数据了。
            //string getjson = "";
            //Root rt = JsonConvert.DeserializeObject<Root>(getjson);
           // get_map_location(1, "3037.9733", "10358.0977", null, null);
            
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void checkBox1_CheckStateChanged(object sender, EventArgs e)
        {
            if (checkBox1.Checked == true)
                textBox1.Enabled = false;
            else
                textBox1.Enabled = true;

        }

        private void button3_Click(object sender, EventArgs e)
        {
            
            if (textBox2.Text != null)
            {
                byte[] data = strToHexByte(textBox2.Text);
                if (data[0] > 0x30 && data[1] > 0x30)//字符串
                {
                    
                    recive_msg_explan(textBox2.Text);
                }
                else
                {
                    
                    reive_msg_hex_explan(data, (uint)data.Length);
                }
            }
            

        }

        private void button4_Click(object sender, EventArgs e)
        {
            richTextBox1.Clear();
        }

        private void button_unsub_Click(object sender, EventArgs e)
        {
            string[] topic = { "" };
            topic[0] = comboBox_subtopic.Text;

           // byte[] qosLevels = new byte[] { MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE }; // qos=1
            client.Unsubscribe(topic);
            OutMsg(richTextBox1, "取消订阅 topic: [" + topic[0] + "]\r\n", Color.Green);
        }

        private void button5_Click(object sender, EventArgs e)
        {
            if(saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                System.IO.Path.GetFullPath(saveFileDialog1.FileName);                             //绝对路径
                System.IO.Path.GetExtension(saveFileDialog1.FileName);                           //文件扩展名
                System.IO.Path.GetFileNameWithoutExtension(saveFileDialog1.FileName);//文件名没有扩展  名
                System.IO.Path.GetFileName(saveFileDialog1.FileName);                          //得到文件
                System.IO.Path.GetDirectoryName(saveFileDialog1.FileName);                  //得到路径
                Debug.WriteLine(saveFileDialog1.FileName);
                Debug.WriteLine(System.IO.Path.GetFullPath(saveFileDialog1.FileName));

                //FileInfo fi = new FileInfo(textBox3.Text);
                //file_len = fi.Length;
                //Debug.WriteLine(fi.Length);
                //fsread = new FileStream(textBox3.Text, FileMode.Open);
            }
        }

        private void checkBox2_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void 图表ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form3 f3 = new Form3();
            //f2.MdiParent = this;
            f3.Show();
        }

        private void tCP升级ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form4 f4 = new Form4();
            //f2.MdiParent = this;
            f4.Show();
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }

        private void button6_Click(object sender, EventArgs e)
        {
            gs84_coord_show_map(textBox3.Text, textBox4.Text);
        }

        private void textBox4_Enter(object sender, EventArgs e)
        {
            if(textBox4.Text=="dd.dddddd")
            {
                textBox4.Text = "";
                textBox4.ForeColor = Color.Black;
            }
            
        }

        private void textBox4_Leave(object sender, EventArgs e)
        {
            if (textBox4.Text == "")
            { 
            textBox4.Text = "dd.dddddd";
                textBox4.ForeColor = Color.Gray;
            }
        }

        private void textBox3_Leave(object sender, EventArgs e)
        {
            if (textBox3.Text == "")
            {
                textBox3.Text = "ddd.dddddd";
                textBox3.ForeColor = Color.Gray;
            }
        }

        private void textBox3_Enter(object sender, EventArgs e)
        {
            if (textBox3.Text == "ddd.dddddd")
            {
                textBox3.Text = "";
                textBox3.ForeColor = Color.Black;
            }
        }

        private void label16_Click(object sender, EventArgs e)
        {

        }

        private void checkBox12_CheckedChanged(object sender, EventArgs e)
        {

        }
        public unsafe static ushort CRC16(byte* bytes,UInt16 len)
        {
            ushort value;
            ushort newLoad = 0xffff, In_value;
            int count = 0;
            for (int i = 0; i < len; i++)
            {
                value = (ushort)bytes[i];
                newLoad = (ushort)(Convert.ToInt32(value) ^ Convert.ToInt32(newLoad));
                In_value = 0xA001;
                while (count < 8)
                {
                    if (Convert.ToInt32(newLoad) % 2 == 1)//判断最低位是否为1
                    {
                        newLoad -= 0x00001;
                        newLoad = (ushort)(Convert.ToInt32(newLoad) / 2);//右移一位
                        count++;//计数器加一
                        newLoad = (ushort)(Convert.ToInt32(newLoad) ^ Convert.ToInt32(In_value));//异或操作
                    }
                    else
                    {
                        newLoad = (ushort)(Convert.ToInt32(newLoad) / 2);//右移一位
                        count++;//计数器加一
                    }
                }
                count = 0;
            }
            return newLoad;
        }

        private uint wait_msg_ack()
        {
            timer1_counter = 0;
            tmr.Start();

#if false
            while (send_msg_id != rev_msg_id)//Console.WriteLine("pub msg : " + msg[0]);
            { 
                Thread.Sleep(100);
                count++;
                if(count>50)
                    return 0;
            }
            return 1;
#else
 
                return 0;
#endif
        }
        byte[] dev_cfg_sendbuf = new byte[128];
        private unsafe void button7_Click(object sender, EventArgs e)
        {
            
            string str;
            uint index = 2;
            Array.Clear(dev_cfg_sendbuf, 0, dev_cfg_sendbuf.Length);
           
            Array.Resize<byte>(ref dev_cfg_sendbuf, 128);
            UInt32 id = (UInt32)DateTimeOffset.UtcNow.ToUnixTimeSeconds() + (8 * 60 * 60);
            send_msg_id = id;
            dev_cfg_sendbuf[index++] = 4;
            dev_cfg_sendbuf[index++] = (byte)DEV_PROP_I.PROP_MSG_UID;
            dev_cfg_sendbuf[index++] = (byte)(id & 0xff);
            dev_cfg_sendbuf[index++] = (byte)(id >> 8);
            dev_cfg_sendbuf[index++] = (byte)(id >> 16);
            dev_cfg_sendbuf[index++] = (byte)(id >> 24);
            if (checkBox_is_active.Checked)//激活
            {
                dev_cfg_sendbuf[index++]= 1;
                dev_cfg_sendbuf[index++] = (byte)DEV_PROP_I.PROP_CFG_ACTIVE;
                dev_cfg_sendbuf[index++] = (byte)comboBox_is_active.SelectedIndex;

            }
            if(checkBox_outside_flag.Checked)//室内外
            {
                dev_cfg_sendbuf[index++] = 1;
                dev_cfg_sendbuf[index++] = (byte)DEV_PROP_I.PROP_CFG_ELEC_FENCE_FLAG;
                dev_cfg_sendbuf[index++]=(byte)comboBox_outside_flag.SelectedIndex;
            }
            if(checkBox_user_info.Checked)
            {
                str = textBox_userinfo.Text;
                byte[] _user_info = Encoding.UTF8.GetBytes(str);
                dev_cfg_sendbuf[index++] = (byte)_user_info.Length;
                dev_cfg_sendbuf[index++] = (byte)DEV_PROP_I.PROP_CFG_USERINFO;

                Array.Copy(_user_info, 0, dev_cfg_sendbuf, index, _user_info.Length);
                index = (byte)(index + _user_info.Length);
            }
            if(checkBox_ble_request_interval.Checked)//请求下行数据频率
            {
                dev_cfg_sendbuf[index++]= 1;
                dev_cfg_sendbuf[index++] = (byte)DEV_PROP_I.PROP_CFG_DOWN_LINK_REQUEST_INTERVAL;
                dev_cfg_sendbuf[index++] =(byte)Convert.ToInt32(comboBox_request_interval.Text);

            }
            if(checkBox_mqtt_server_info.Checked)//服务器地址
            {
                str = comboBox_mqtt_server_info.Text;
                byte[] server_info= Encoding.UTF8.GetBytes(str);
                Debug.WriteLine("SERVER INFO" + byteToHexStr(server_info, (uint)server_info.Length));
                dev_cfg_sendbuf[index++] = (byte)server_info.Length;
                dev_cfg_sendbuf[index++] = (byte)DEV_PROP_I.PR0P_CFG_SERVER_INFO; 
                 
                Array.Copy(server_info,0,  dev_cfg_sendbuf,index, server_info.Length);
                index =(byte)(index+ server_info.Length);
            }
            if (checkBox_mqtt_user_info.Checked)//用户名密码
            {
                str = comboBox_mqtt_user_info.Text;
                
                byte[] mqtt_user_info = Encoding.UTF8.GetBytes(str);
                dev_cfg_sendbuf[index++] = (byte)mqtt_user_info.Length;
                dev_cfg_sendbuf[index++] = (byte)DEV_PROP_I.PROP_CFG_USER_PWD_INFO;
                
                Array.Copy(mqtt_user_info,0, dev_cfg_sendbuf,index, mqtt_user_info.Length);
                index = (byte)(index + mqtt_user_info.Length);
            }
            if (checkBox_loc_mode.Checked)//优先定位方式
            {
                dev_cfg_sendbuf[index++] = 1;
                dev_cfg_sendbuf[index++] = (byte)DEV_PROP_I.PROP_CFG_OUTSIDE_LOC_MODE;
                dev_cfg_sendbuf[index++] = (byte)comboBox_loc_mode.SelectedIndex;

            }
            if (checkBox_loc_tasic.Checked)//定位策略
            {
                dev_cfg_sendbuf[index++] = 1;
                dev_cfg_sendbuf[index++] = (byte)DEV_PROP_I.PROP_CFG_OUTSIDE_LOC_TACTICS;
                dev_cfg_sendbuf[index++] = (byte)comboBox_loctaisc.SelectedIndex;
            }
            if (checkBox_net_heart.Checked)//心跳间隔
            {
                ushort net_heart= Convert.ToUInt16(comboBox_net_heart_interval.Text);
                dev_cfg_sendbuf[index++] = 2;
                dev_cfg_sendbuf[index++] = (byte)DEV_PROP_I.PROP_CFG_NETHEAR_INTERVAL;
                dev_cfg_sendbuf[index++] = (byte)(net_heart & 0xff);
                dev_cfg_sendbuf[index++]=(byte)(net_heart >> 8);
                
            }
            if (checkBox_measure_interval.Checked)//测量间隔
            {
                ushort measure_interval = Convert.ToUInt16(comboBox_measure_interval.Text);
                dev_cfg_sendbuf[index++] = 2;
                dev_cfg_sendbuf[index++] = (byte)DEV_PROP_I.PROP_CFG_HUMAN_SIGNS_MEASURE_INTERVAL;
                dev_cfg_sendbuf[index++] = (byte)(measure_interval & 0xff);
                dev_cfg_sendbuf[index++] = (byte)(measure_interval >> 8);
            }
            if(checkBox_measure_time.Checked)//测量时间
            {
                ushort measure_time = Convert.ToUInt16(comboBox_measure_time.Text);
                dev_cfg_sendbuf[index++] = 2;
                dev_cfg_sendbuf[index++] = (byte)DEV_PROP_I.PROP_CFG_HUMAN_SIGNS_MEASURE_TIME;
                dev_cfg_sendbuf[index++] = (byte)(measure_time & 0xff);
                dev_cfg_sendbuf[index++] = (byte)(measure_time >> 8);
            }
            if(checkBox_loc_interval.Checked)//室外定位间隔
            {
                ushort loc_interval = Convert.ToUInt16(comboBox_loc_interval.Text);
                dev_cfg_sendbuf[index++] = 2;
                dev_cfg_sendbuf[index++] = (byte)DEV_PROP_I.PROP_CFG_OUTSIDE_LOC_INTERVAL;
                dev_cfg_sendbuf[index++] = (byte)(loc_interval & 0xff);
                dev_cfg_sendbuf[index++] = (byte)(loc_interval >> 8);
            }
            if (checkBox_aoa_interval.Checked)//室内定位间隔
            {
                ushort aoa_interval = Convert.ToUInt16(comboBox_aoa_interval.Text);
                dev_cfg_sendbuf[index++] = 2;
                dev_cfg_sendbuf[index++] = (byte)DEV_PROP_I.PROP_CFG_AOA_INTERVAL;
                dev_cfg_sendbuf[index++] = (byte)(aoa_interval & 0xff);
                dev_cfg_sendbuf[index++] = (byte)(aoa_interval >> 8);
            }
            if (checkBox_heart_th.Checked)//心率阈值
            {
                dev_cfg_sendbuf[index++] = 2;
                dev_cfg_sendbuf[index++] = (byte)DEV_PROP_I.PROP_CFG_HEART_TH;
                dev_cfg_sendbuf[index++] = (byte)Convert.ToInt32(comboBox_hr_th_min.Text);
                dev_cfg_sendbuf[index++] = (byte)Convert.ToInt32(comboBox_hr_th_max.Text);
            }
            if (checkBox_spo2_th.Checked)
            {
                dev_cfg_sendbuf[index++] = 1;
                dev_cfg_sendbuf[index++] = (byte)DEV_PROP_I.PROP_CFG_SPO2_TH;
                dev_cfg_sendbuf[index++] = (byte)Convert.ToInt32(comboBox_spo2_th.Text);
                
            }
            if (checkBox_bat_th.Checked)
            {
                dev_cfg_sendbuf[index++] = 1;
                dev_cfg_sendbuf[index++] = (byte)DEV_PROP_I.PROP_CFG_BAT_TH;
                dev_cfg_sendbuf[index++] = (byte)Convert.ToInt32(comboBox_bat_th.Text);
            }
            if(checkBox_syn_dev_time.Checked)
            {
                UInt32 tamps= (UInt32)DateTimeOffset.UtcNow.ToUnixTimeSeconds()+(8*60*60);
                dev_cfg_sendbuf[index++] = 4;
                dev_cfg_sendbuf[index++] = (byte)DEV_PROP_I.PROP_CFG_DEV_TIME;
                dev_cfg_sendbuf[index++] = (byte)(tamps & 0xff);
                dev_cfg_sendbuf[index++] = (byte)(tamps >>8);
                dev_cfg_sendbuf[index++] = (byte)(tamps >>16);
                dev_cfg_sendbuf[index++] = (byte)(tamps >>24);
            }
            if(checkBox_devctrlcmd.Checked)
            {
                dev_cfg_sendbuf[index++] = 1;
                dev_cfg_sendbuf[index++] = (byte)DEV_PROP_I.PROP_CTRL_DEV;
                dev_cfg_sendbuf[index++] = (byte)(comboBox_devctrlcmd.SelectedIndex+1);
            }
            fixed (byte* ptr = &dev_cfg_sendbuf[2])
            {
                UInt16 _crc = CRC16(ptr, (ushort)(index-2));


                dev_cfg_sendbuf[0] = (byte)((index - 2) & 0XFF);
                dev_cfg_sendbuf[1] = (byte)((index - 2) >> 8);
                dev_cfg_sendbuf[index++] = (byte)(_crc & 0xff);
                dev_cfg_sendbuf[index++] = (byte)(_crc >> 8);
            }

            Array.Resize<byte>(ref dev_cfg_sendbuf, (int)index);
            OutMsg(richTextBox1, "[" + System.DateTime.Now.ToString("F") + "] MQTT[TOPIC:" + textBox_pub_topic.Text + "]发送" + index + "字节：", Color.Blue);
            OutMsg(richTextBox1, byteToHexStr(dev_cfg_sendbuf, (uint)index) + "\r\n", Color.Red);
            reive_msg_hex_explan(dev_cfg_sendbuf,index);

#if true
            if (textBox_pub_topic.Text != "")
            {
                string[] topic = { "" };
                topic[0] = textBox_pub_topic.Text;
                str = comboBox_pub.Text;
                
#if true
                ushort msgId = client.Publish(topic[0], // topic
                                                 dev_cfg_sendbuf, // message body
                                                 1, // pub的QoS level
                                                 checkBox_mqtt_retainid.Checked); // retainid

               cfg_timer_counter = 0;
               send_cfg_tmr.Start();
                send_cfg_tmr.Enabled = true;

#endif
            }
            else
            {
                MessageBox.Show("请设置发送TOPIC");
            }

#endif

            }
        byte[] dev_msg_sendbuf = new byte[256];
        private unsafe void button8_Click(object sender, EventArgs e)
        {
            
            
            string str;
            uint index = 2;
            Array.Clear(dev_msg_sendbuf,0,dev_msg_sendbuf.Length);
            Array.Resize<byte>(ref dev_msg_sendbuf, 256);
            UInt32 id = (UInt32)DateTimeOffset.UtcNow.ToUnixTimeSeconds() + (8 * 60 * 60);
            send_msg_id = id;
            dev_msg_sendbuf[index++] = 4;
            dev_msg_sendbuf[index++] = (byte)DEV_PROP_I.PROP_MSG_UID;
            dev_msg_sendbuf[index++] = (byte)(id & 0xff);
            dev_msg_sendbuf[index++] = (byte)(id >> 8);
            dev_msg_sendbuf[index++] = (byte)(id >> 16);
            dev_msg_sendbuf[index++] = (byte)(id >> 24);
            str = textBox_msg_sender.Text;

            byte[] msgsender = Encoding.UTF8.GetBytes(str);
            dev_msg_sendbuf[index++] = (byte)msgsender.Length;
            if (msgsender.Length > 64)
            {
                MessageBox.Show("标题长度超过64");
                return;
            }
            dev_msg_sendbuf[index++] = (byte)DEV_PROP_I.PROP_MSG_SENDER;
            Array.Copy(msgsender, 0, dev_msg_sendbuf, index, msgsender.Length);
            index = (byte)(index + msgsender.Length);

            str = textBox_msg_content.Text;

            byte[] msgcontent = Encoding.UTF8.GetBytes(str);
            dev_msg_sendbuf[index++] = (byte)msgcontent.Length;
            if (msgcontent.Length > 64)
            {
                MessageBox.Show("消息内容长度超过256");
                return;
            }
            dev_msg_sendbuf[index++] = (byte)DEV_PROP_I.PROP_MSG_CONTEN;
            Array.Copy(msgcontent, 0, dev_msg_sendbuf, index, msgcontent.Length);
            index = (byte)(index + msgcontent.Length);

            fixed (byte* ptr = &dev_msg_sendbuf[2])
            {
                UInt16 _crc = CRC16(ptr, (ushort)(index - 2));


                dev_msg_sendbuf[0] = (byte)((index - 2) & 0XFF);
                dev_msg_sendbuf[1] = (byte)((index - 2) >> 8);
                dev_msg_sendbuf[index++] = (byte)(_crc & 0xff);
                dev_msg_sendbuf[index++] = (byte)(_crc >> 8);
            }

            Array.Resize<byte>(ref dev_msg_sendbuf, (int)index);
            OutMsg(richTextBox1, "[" + System.DateTime.Now.ToString("F") + "] MQTT[TOPIC:" + textBox_pub_topic.Text + "]发送" + index + "字节：", Color.Blue);
            OutMsg(richTextBox1, byteToHexStr(dev_msg_sendbuf, (uint)index) + "\r\n", Color.Red);
            
            reive_msg_hex_explan(dev_msg_sendbuf, index);
#if true
            if (textBox_pub_topic.Text != "")
            {
                string[] topic = { "" };
                topic[0] = textBox_pub_topic.Text;
                str = comboBox_pub.Text;
                
#if true
                ushort msgId = client.Publish(topic[0], // topic
                                                 dev_msg_sendbuf, // message body
                                                1, // pub的QoS level
                                                 checkBox_mqtt_retainid.Checked); // retainid
                                                                                  //Console.WriteLine("pub msg : " + msg[0]);
#endif
                if (checkBox_mqtt_retainid.Checked == false)
                {
                    timer1_counter = 0;
                    tmr.Start();
                    tmr.Enabled = true;
                }

            }
            else
            {
                MessageBox.Show("请设置发送TOPIC");
            }

#endif
        }
        UInt32 rev_msg_id, send_msg_id;
        UInt32 timer1_counter=0;
        private void OnTmrTrg(object sender, EventArgs e)
        {
            if (send_msg_id != rev_msg_id)
            {
                timer1_counter++;
                if (timer1_counter > 5)
                {
                    tmr.Stop();
                    tmr.Enabled = false;
                    OutMsg(richTextBox1, "发送失败，设备下次上报数据时再次发送", Color.Red);
                    mqtt_msg_pub_queue.Enqueue(dev_msg_sendbuf);
                }
            }
            else
            {
                tmr.Stop();
                tmr.Enabled = false;
                //OutMsg(richTextBox1, "发送成功", Color.Green);
            }

        }
        UInt32 cfg_timer_counter = 0;
        private void OncfgTmrTrg(object sender, EventArgs e)
        {
            if (send_msg_id != rev_msg_id)
            {
                cfg_timer_counter++;
                if (cfg_timer_counter > 5)
                {
                    send_cfg_tmr.Stop();
                    send_cfg_tmr.Enabled = false;
                    OutMsg(richTextBox1, "发送失败，设备下次上报数据时再次发送", Color.Red);
                    mqtt_msg_pub_queue.Enqueue(dev_cfg_sendbuf);
                }
            }
            else
            {
                send_cfg_tmr.Stop();
                send_cfg_tmr.Enabled = false;
                //OutMsg(richTextBox1, "发送成功", Color.Green);
            }

        }
    }
    public class Root
    {
        /// <summary>
        /// 
        /// </summary>
        public string status { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string info { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string infocode { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string locations { get; set; }
    }
}
